/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package client;
import java.io.*;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Hashtable;
import java.util.LinkedList;
import javax.imageio.stream.FileImageInputStream;
import javax.imageio.stream.FileImageOutputStream;
/**
 *
 * @author juan
 */
public class DTP implements Runnable{
    public DTP(String host, int port, int connType, PI pi,int operation,String arg) {
        this.pi = pi;
        this.host = host;
        this.port = port;
        this.connType = connType;
        this.operation = operation;
        this.operationArgument = arg;
    }

    public void run() {
        switch(operation) {
            case RETR:
                retrieveFile();
                break;
            case STOR:
                storeFile();
                break;
        }
    }

    public void connect() {
        try {

            if(connType == PASSIVE) {
                socket = new Socket(host, port);
            } else {
                String ip = host.replace('.', ',');
                ServerSocket ss = new ServerSocket(0);
                int lp = ss.getLocalPort();
                pi.sendCommand("PORT %s,%s,%s", ip, (lp & 65280) >> 8, (lp & 255));
                socket = ss.accept();
                pi.getResponse();
                ss.close();
            }
            dcin = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            dcout = new PrintStream(socket.getOutputStream());

        } catch (Exception e) {
            // TODO notify the user about error.
            System.out.println(e);
            e.printStackTrace();
            return;
        }
    }

    public void retrieveFile() {
        try {
            InputStream is = socket.getInputStream();
            File file = new File(operationArgument);
            if(file.exists())
                file.delete();
            file.createNewFile();
            RemoteFile rFile = pi.fileDataDic.get(file.getName());
            FileImageOutputStream fos = new FileImageOutputStream(file);



            byte buffer[] = new byte[DTP.BUFFER_SIZE];
            //System.out.println("Start reading available:");

            int totalReaded = 0;
            TransferData td = new TransferData(file.getName(), "Download");
            pi.gui.insertTransfer(td);
            while (true) {
                int readed = is.read(buffer);
                totalReaded += readed;

                if (readed == -1) {
                    break;
                }
                
                td.setCompletion((int)((float)totalReaded/(float)rFile.getSize()*100));
                pi.gui.updateTransferCompletion(td);

                fos.write(buffer, 0, readed);
            }
            fos.flush();
            fos.close();
            //System.out.println("Done reading");
        }catch(Exception e){

            e.printStackTrace();
        // TODO
        }
    }

    public void storeFile() {
        try {

            File file = new File(operationArgument);
            FileImageInputStream fis = new FileImageInputStream(file);
            byte buffer[] = new byte[DTP.BUFFER_SIZE];
            TransferData td = new TransferData(file.getName(), "Upload");
            pi.gui.insertTransfer(td);
            int totalReaded = 0;
            while (true) {
                int readed = fis.read(buffer);
                totalReaded += readed;
                if (readed == -1) {
                    break;
                }
                td.setCompletion((int)((float)totalReaded/(float)file.length()*100));
                pi.gui.updateTransferCompletion(td);
                dcout.write(buffer, 0, readed);
            }
            dcout.flush();
            dcout.close();
            socket.close();
        }catch(Exception e){
            System.out.println(e);
            e.printStackTrace();
            // TODO
        }
    }

    public LinkedList recieveList() {
        
        LinkedList<RemoteFile> ret = new LinkedList<RemoteFile>();
        try {

            pi.fileDataDic = new Hashtable<String, RemoteFile>();
            String msg = dcin.readLine();

            while(msg!=null) {

                RemoteFile rf = new RemoteFile(msg);
                ret.add(rf);
                pi.fileDataDic.put(msg, rf);

                msg = dcin.readLine();
            }
        } catch(Exception e) {
            // TODO error
            System.out.println(e);
            e.printStackTrace();
            return null;
        }
        
        return ret;
    }

    public void closeConnection() {
        
    }
    public String arg;
    //reference to pi thread
    PI pi = null;
    //variables for configuration
    public int port,connType;
    public String host;
    int operation;
    String operationArgument;
    //variables for connection and connection I/O
    BufferedReader dcin;
    PrintStream dcout;
    Socket socket;
    //constants

    
    public static final int PASSIVE=0,ACTIVE=1,BUFFER_SIZE=65536,LIST=2,RETR=3,STOR=4;
}